//GA+SA common
//$Id: ga_sa_common.h 441 2010-04-09 17:27:20Z Oleg.Bulychov $
#pragma once

#include "solvers/sa/sa_common.h"
#include "solvers/ga/ga_common.h"

namespace ga
{

namespace inter_operator
{

template<class E, class T>
class sa:
    public factory_object< sa<E, T>, abstract_operator<E, T> >
{
    typedef SA_Traits<E> sa_traits;
    SA<sa_traits>  sa_;
    double         probability_;
public:
    explicit sa()
    {
        accept(meta::set_default_values());
    }

    static char const* get_Name() { return "sa"; }

    template<class V>
    void accept(V& v)
    {
        v(VAR_(probability),   0.01);
        v(sa_, "/");
    }

    virtual void apply(T** list, int size,
        E* env,
        int rank,
        int thread_id,
        int step,
        int max_step,
        uniform_random& rnd)
    {
        //KProfiler pr("sa");
        sa_.init(env, rank, thread_id, true);
        for (int i = 0; i < size; ++i)
        {
            if (rnd.next_Double() < probability_)
            {
                list[i]->evaluate(env, rnd);
                sa_.solve(*list[i]);
            }
        }
    }
};

}//:inter_operator

}//:ga


struct validator_ga_sa_tag
{};

template<class E, class T>
struct validator_ga<E, T, validator_ga_sa_tag>: public meta::abstract_validator
{
    template<class U>
    void set_Default(std::vector< ref_ptr<U> >& v) const
    {
        v.clear();
        ref_ptr<U> pt;
        using namespace ga::inter_operator;
        {
            sa<E, T>* px = new sa<E, T>;
            pt.attach(px);
            v.push_back(pt);
        }
        {
            crossover<E, T>* px = new crossover<E, T>;
            pt.attach(px);
            v.push_back(pt);
        }
        {
            mutation<E, T>* px = new mutation<E, T>;
            pt.attach(px);
            v.push_back(pt);
        }
    }
};


//EOF!
